//-----------------------------------------------------------------------
// <copyright file="Login.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
// </copyright>
// <author>Barry Dorrans</author>
// <email>barryd@charteris.com</email>
// <date>2005-07-18</date>
// <summary>Build task to logout a pushed user context</summary>
//-----------------------------------------------------------------------

namespace Microsoft.Sdc.Tasks.Security
{
  using System;
  using System.Collections.Generic;
  using System.Text;
  using Microsoft.Build.Tasks;
  using Microsoft.Build.Framework;
  using Microsoft.Build.Utilities;
  using System.Runtime.InteropServices;
  using System.Security.Principal;
  using System.Security.Permissions;

  /// <summary>
  /// Logs out the current security context created by the <see cref="Microsoft.Sdc.Tasks.Security.Login"/> task.
  /// </summary>
  /// <remarks>
  /// <code><![CDATA[<Security.Logout/>]]></code>
  /// </remarks>
  public class Logout : TaskBase
  {
    /// <summary>
    /// Logs out a previous <see cref="Microsoft.Sdc.Tasks.Security.Login"/> task.
    /// </summary>
    public Logout()
    {
    }

    /// <summary>
    /// Performs the action of this task.
    /// </summary>
    protected override void InternalExecute()
    {
      if (0 == contextStacks.processHandles.Count || 0 == contextStacks.impersonationContexts.Count)
        throw new TaskException(
          Log.FormatResourceString("Security.Logout.NoStackedLogins"));
      else if (contextStacks.processHandles.Count != contextStacks.impersonationContexts.Count)
        throw new TaskException(
          Log.FormatResourceString("Security.Logout.StackSyncError"));
      else
      {
        WindowsImpersonationContext impersonatedUser = contextStacks.impersonationContexts.Pop();
        IntPtr userHandle = contextStacks.processHandles.Pop();
        impersonatedUser.Undo();
        if (userHandle != IntPtr.Zero)
          NativeMethods.CloseHandle(userHandle);
      }
    }



    /// <summary>
    /// Imported Win32 API functions.
    /// </summary>
    internal class NativeMethods
    {
      [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
      public extern static bool CloseHandle(IntPtr handle);
    }

  }
}
